# -*- coding:utf-8 -*-
"""
Created on 1 Dec 2009
"""
__author__ = 'Ilias Karampatsos'

from reportlab.graphics.shapes import Drawing,colors
from reportlab.graphics.charts.axes import YValueAxis

class Graph():
    def __init__(self,width,height):
        self.DRAWING_WIDTH=width
        self.DRAWING_HEIGHT=height
        self.graphTitle=''
    def getGraphDrawing(self):
        pass
class TwoAxesGraph(Graph):
    def __init__(self,width=800,height=200):
        Graph.__init__(self, width, height)
        #self.DRAWING_WIDTH=width
        #self.DRAWING_HEIGHT=height
        
        self.graphLeft=None
        self.graphLeftTitle=''
        self.graphRight=None
        self.graphRightTitle=''
        
        self.data={}
        self.bothAxesMinValue=0
    def setLeft(self,graph,data,title=''):
        if type(data) not in (type([]),type(())):raise NameError('Need at least 1 list in the left data')
        self.graphLeft=graph
        self.graphLeftTitle=title
        self.data['left']=data
    def setRight(self,graph,data,title=''):
        if type(data) not in (type([]),type(())):raise NameError('Need at least 1 list in the left data')
        self.graphRight=graph
        self.graphRightTitle=title
        self.data['right']=data
    def addLabels(self,labels):
        #Need 3 lists. Labels, right  and left data
        if type(labels[0]) in (type([]),type(())):raise NameError('Need at least flat data')
        self.data['labels']=labels
    def checkData(self):
        #Need 3 lists. Labels, right  and left data
        if type(self.data['left'][0]) not in (type([]),type(())):raise NameError('Need at least 1 lists in the left data')
        if type(self.data['right'][0]) not in (type([]),type(())):raise NameError('Need at least 1 lists in the right data')
        rows=len(self.data['left'][0])
        for data in self.data['left']:
            if rows<>len(data):
                raise NameError('Data do not have equal rows')

    def getDataRows(self):
        return len(self.data['left'][0])
    def getGraphDrawingStandardFormat(self):
        self.checkData()
        noOfBars=self.getDataRows()
        drawing=Drawing(self.DRAWING_WIDTH,self.DRAWING_HEIGHT)

        data = self.data['left']
        bc = self.graphLeft
        bc.x = 35
        bc.y = 35
        bc.height = self.DRAWING_HEIGHT-50
        bc.width = self.DRAWING_WIDTH-2*bc.x
        bc.data = data
        
        bc.groupSpacing=2
        bc.bars.strokeColor = colors.green
        for bar in range(noOfBars):
            bc.bars[bar].fillColor = colors.peachpuff
        bc.valueAxis.valueMin = self.bothAxesMinValue
        bc.valueAxis.valueMax = 1.1*max(map(max,self.data['left']))
        

        bc.categoryAxis.categoryNames = self.data['labels']
        #bc.valueAxis.valueStep = 10
        bc.categoryAxis.labels.boxAnchor = 'ne'
        #bc.categoryAxis.labels.dx = -1
        #bc.categoryAxis.labels.dy = -2
        bc.categoryAxis.labels.angle = 45
        for label in range(len(self.data['labels'])):
            bc.categoryAxis.labels[label].fontSize=7
        drawing.add(bc)
        
        data3=[]
        for lineData in self.data['right']:
            data3.append([])
            for point in range(noOfBars):
                data3[-1].append((point+0.5,lineData[point])) 

        lp = self.graphRight
        lp.x = bc.x
        lp.y = bc.y
        lp.height = bc.height
        lp.width = bc.width
        lp.data = data3
        lp.joinedLines = 1
        #lp.lines[1].symbol = makeMarker('FilledCircle')
        from reportlab.graphics.widgets.markers import makeMarker
        lp.lines[0].symbol = makeMarker('Circle')
        lp.lines[0].strokeColor=colors.blue
        lp.lineLabelFormat = '%2.0f'
        lp.strokeColor = colors.black
        lp.xValueAxis.valueMin = 0
        lp.xValueAxis.valueMax = noOfBars
        #lp.xValueAxis.valueSteps = [1, 2, 3, 4, 5,6,7,8]
        lp.xValueAxis.labelTextFormat = '%2.1f'
        lp.yValueAxis.valueMin = self.bothAxesMinValue
        lp.yValueAxis.valueMax = 1.1*max(map(max,self.data['right']))
        lp.xValueAxis.visible=False
        lp.yValueAxis.visible=False
        #lp.yValueAxis.valueSteps = [0,1, 2, 3, 5, 6]
        drawing.add(lp)
        
        y2Axis = YValueAxis()
        y2Axis.setProperties(lp.yValueAxis.getProperties())
        y2Axis.setPosition(lp.x+lp.width,lp.y,lp.height)
        y2Axis.tickRight=5
        y2Axis.tickLeft=0
        y2Axis.labels.dx = 20
        
        y2Axis.configure(data3)
        y2Axis.visible=True
        drawing.add(y2Axis)

        from reportlab.graphics.charts.textlabels import Label
        if self.graphRightTitle:
            labBC = Label()
            labBC.setOrigin(bc.x/2.5,self.DRAWING_HEIGHT/2)
            labBC.angle = 90
            labBC.setText(self.graphRightTitle)
            drawing.add(labBC)
        if self.graphLeftTitle:
            labLine = Label()
            labLine.setOrigin(self.DRAWING_WIDTH-bc.x/2.5,self.DRAWING_HEIGHT/2)
            labLine.angle = 90
            labLine.setText(self.graphLeftTitle)
            drawing.add(labLine)
            
        return drawing
    def getGraphDrawing(self):
        self.checkData()
        noOfBars=self.getDataRows()
        drawing=Drawing(self.DRAWING_WIDTH,self.DRAWING_HEIGHT)
        
        dataLeft = self.data['left']
        bc = self.graphLeft
        bc.x = 45
        bc.y = 35
        bc.height = self.DRAWING_HEIGHT-50
        bc.width = self.DRAWING_WIDTH-2*bc.x
        bc.data = dataLeft
        
        bc.valueAxis.valueMin = self.bothAxesMinValue
        bc.valueAxis.valueMax = 1.1*max(map(max,dataLeft))
        bc.categoryAxis.categoryNames = self.data['labels']
        drawing.add(bc)
        
        data3=[]
        for lineData in self.data['right']:
            data3.append([])
            for point in range(noOfBars):
                data3[-1].append((point+0.5,lineData[point])) 

        lp = self.graphRight
        lp.x = bc.x
        lp.y = bc.y
        lp.height = bc.height
        lp.width = bc.width
        lp.data = data3

        from reportlab.graphics.widgets.markers import makeMarker
        lp.lines[0].symbol = makeMarker('Circle')
        lp.lines[0].strokeColor=colors.blue
        lp.lineLabelFormat = '%2.0f'
        
        lp.xValueAxis.valueMin = 0
        lp.xValueAxis.valueMax = noOfBars
        lp.yValueAxis.valueMin = self.bothAxesMinValue
        lp.yValueAxis.valueMax = 1.1*max(map(max,self.data['right']))
        lp.xValueAxis.visible=False
        lp.yValueAxis.visible=False
        drawing.add(lp)
        
        y2Axis = YValueAxis()
        y2Axis.setProperties(lp.yValueAxis.getProperties())
        y2Axis.setPosition(lp.x+lp.width,lp.y,lp.height)
        y2Axis.tickRight=5
        y2Axis.tickLeft=0
        y2Axis.labels.dx = 20
        
        y2Axis.configure(data3)
        y2Axis.visible=True
        drawing.add(y2Axis)

        from reportlab.graphics.charts.textlabels import Label
        if self.graphRightTitle:
            labBC = Label()
            labBC.setOrigin(bc.x/2.5,self.DRAWING_HEIGHT/2)
            labBC.angle = 90
            labBC.setText(self.graphRightTitle)
            #labBC.fontName='Times-Bold'
            labBC.fontSize=12
            #labBC.boxStrokeColor=colors.black
            drawing.add(labBC)
        if self.graphLeftTitle:
            labLine = Label()
            labLine.setOrigin(self.DRAWING_WIDTH-bc.x/4,self.DRAWING_HEIGHT/2)
            labLine.angle = 90
            labLine.setText(self.graphLeftTitle)
            #labLine.fontName='Times-Bold'
            labLine.fontSize=12
            #labBC.boxStrokeColor=colors.black
            drawing.add(labLine)
        if self.graphTitle:
            labTitle = Label()
            labTitle.setOrigin(self.DRAWING_WIDTH/2,self.DRAWING_HEIGHT-5)
            labTitle.angle = 0
            labTitle.setText(self.graphTitle)
            labTitle.fontName='Times-Bold'
            labTitle.fontSize=12
            #labBC.boxStrokeColor=colors.black
            drawing.add(labTitle)
            
        return drawing


def useClass():
    from reportlab.graphics.charts.barcharts import VerticalBarChart
    from reportlab.graphics.charts.lineplots import LinePlot
    from reportlab.graphics import renderPDF
    from reportlab.graphics import renderPM
    
    
    

    labels=['Jan-99','Feb-99','Mar-99']
    dl=[(13, 5, 20)]
    dr=[(3.1, 5, 2)]
    
    m=TwoAxesGraph()
    m.setLeft(VerticalBarChart(),dl,'Average Premium')
    m.setRight(LinePlot(), dr,'Quotability')
    m.addLabels(labels)
    m.graphTitle='My test title'
    drawing=m.getGraphDrawing()
    renderPDF.drawToFile(drawing, '../tmp/barLineClass.pdf')
    #renderPM.drawToFile(drawing, '../tmp/out.gif', 'GIF')    

if __name__=='__main__':
    useClass()
    print "Finished"